#include "ConvertRst.h"

#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include <unistd.h>
#endif
#include <iostream>
#include <map>
#include <vector>

#include <Python.h>

// #include "IBE_AnsysRstReader.h"
// #include "IBE_DataInformationToVTK.h"
// #include "IBE_Common.h"

static std::string vtkFilePath_ = "";

// ----------------------------------------------------------------------------
ConvertRst::ConvertRst()
{
}

// ----------------------------------------------------------------------------
ConvertRst::~ConvertRst()
{
}

// ----------------------------------------------------------------------------
int ConvertRst::ConvertRstToFile(std::string inputFile, std::string outputDir, int outType)
{
    if (outType != 0 && outType != 1)
    {
        return 0;
    }

    // 去除前后空格
    //inputFile = ibe_common::IBE_Common::StringTrimmed(inputFile.c_str());
    //outputDir = ibe_common::IBE_Common::StringTrimmed(outputDir.c_str());
    if (inputFile.empty() || outputDir.empty())
    {
        return 0;
    }

    Py_Initialize(); // 只调用一次
    if (!Py_IsInitialized()) // 判断是否初始化成功
    {
        std::cout << "Python Initialize failed." << std::endl;
        return 0;
    }
#ifdef _WIN32
#else
    PyObject* sys = PyImport_ImportModule("sys");
    PyObject* path = PyObject_GetAttrString(sys, "path");
    //std::string py_file_path = "/mnt/convert_code/cmake-build-debug/Release";
    //PyList_Append(path, PyUnicode_FromString(py_file_path.c_str()));
#endif
    vtkFilePath_ = "";

    // 获取输入文件名
    std::string inFileName = inputFile;
    auto slashPos = inputFile.find_last_of("/");
    if (slashPos != std::string::npos)
    {
        inFileName = inputFile.substr(slashPos + 1);
    }

    std::string outFolderDir_vtk = "";
    std::string outFolderDir_gmsh = "";
    {
        auto dot_pos = inFileName.find_last_of('.');
        std::string fileName = inFileName;
        if (dot_pos != std::string::npos)
        {
            fileName = inFileName.substr(0, dot_pos);
        }
        outFolderDir_vtk = outputDir + "/" + fileName + ".vtk";
        outFolderDir_gmsh = outputDir + "/" + fileName + ".gmsh";
        // 判断文件是否存在:0-存在，-1-不存在 
        if (access(outFolderDir_vtk.c_str(), 0) == -1)
        {
            // 创建文件夹
#ifdef _WIN32
            mkdir(outFolderDir_vtk.c_str());
#else
            mkdir(outFolderDir_vtk.c_str(), 0755);
#endif
        }
        // 判断文件是否存在:0-存在，-1-不存在 
        if (access(outFolderDir_gmsh.c_str(), 0) == -1)
        {
            // 创建文件夹
#ifdef _WIN32
            mkdir(outFolderDir_gmsh.c_str());
#else
            mkdir(outFolderDir_gmsh.c_str(), 0755);
#endif
        }
    }

    int conVtkResult = ConvertRst::ConvertRstToVTK(inputFile, outFolderDir_vtk);
    if (outType == 1) // to gmsh
    {
        if (conVtkResult == 1 && !vtkFilePath_.empty())
        {
            conVtkResult = ConvertRst::ConvertRstToGmsh(inputFile, outFolderDir_gmsh);
        }
        else
        {
            conVtkResult = 0;
        }
    }

    Py_Finalize(); // 只调用一次

    return conVtkResult;
}

// ----------------------------------------------------------------------------
int ConvertRst::ConvertRstToVTK(std::string inputFile, std::string outputDir)
{
    int convertState = 0;
    std::vector<PyObject*> pyObjects;
    try
    {
        std::cout << "Start convert \"" << inputFile << "\" to \"" << outputDir << "\"." << std::endl;
        PyObject* module = PyImport_ImportModule("ConvertRstToVtk");
        if (!module)
        {
            std::logic_error ex("Python get module(ConvertRstToVtk) failed.");
            throw std::exception(ex);
        }
        pyObjects.emplace_back(module);

        std::cout << "[CONVERSION PROCESS] 25%" << std::endl;

        // rst转vtk的转换接口
        PyObject* func = PyObject_GetAttrString(module, "RstToVtk");
        if (!func || !PyCallable_Check(func))
        {
            std::logic_error ex("Can't find the function(RstToVtk).");
            throw std::exception(ex);
        }
        pyObjects.emplace_back(func);

        std::cout << "[CONVERSION PROCESS] 50%" << std::endl;

        // 构造参数
        PyObject* func_args = PyTuple_New(2);
        PyTuple_SetItem(func_args, 0, PyUnicode_FromString(inputFile.c_str()));
        PyTuple_SetItem(func_args, 1, PyUnicode_FromString(outputDir.c_str()));
        pyObjects.emplace_back(func_args);

        std::cout << "[CONVERSION PROCESS] 75%" << std::endl;

        // 调用转换接口
        PyObject* func_py = PyObject_CallObject(func, func_args);
        if (!func_py)
        {
            std::logic_error ex("RstToVtk failed.");
            throw std::exception(ex);
        }
        if (PyUnicode_Check(func_py))
        {
            vtkFilePath_ = PyUnicode_AsUTF8(func_py);
        }
        pyObjects.emplace_back(func_py);

        std::cout << "[CONVERSION PROCESS] 100%" << std::endl;
        convertState = 1;
    }
    catch (const std::exception& ex)
    {
        convertState = 0;
        std::cerr << "[ERROR] ConvertRstToVTK: " << ex.what() << std::endl;
        if (PyErr_Occurred())
        {
            PyErr_Print();
        }
    }

    // 释放python空间
    // Py_XDECREF和Py_DECREF功能相同，但可以处理空指针
    for (auto it = pyObjects.rbegin(); it != pyObjects.rend(); it++)
    {
        Py_XDECREF(*it); // 释放python空间
    }
    std::vector<PyObject*>().swap(pyObjects);

    return convertState;
}

// ----------------------------------------------------------------------------
int ConvertRst::ConvertRstToGmsh(std::string inputFile, std::string outputDir)
{
    int convertState = 0;
    std::vector<PyObject*> pyObjects;

    try
    {
        std::cout << "Start convert \"" << inputFile << "\" to \"" << outputDir << "\"." << std::endl;

        //导入模块 
        PyObject* module = PyImport_ImportModule("ConvertVtkToGmsh_RST");
        if (!module)
        {
            std::logic_error ex("Python get module(ConvertVtkToGmsh_RST) failed.");
            throw std::exception(ex);
        }
        pyObjects.emplace_back(module);

        std::cout << "[CONVERSION PROCESS] 25%" << std::endl;

        // vtk转gmsh的转换接口
        PyObject* func = PyObject_GetAttrString(module, "MultiVtkToGmsh");
        if (!func || !PyCallable_Check(func))
        {
            std::logic_error ex("Can't find the function(MultiVtkToGmsh).");
            throw std::exception(ex);
        }
        pyObjects.emplace_back(func);

        std::cout << "[CONVERSION PROCESS] 50%" << std::endl;

        // 构造参数
        std::vector<std::string> seriesFilePaths;
        seriesFilePaths.emplace_back(vtkFilePath_);
        PyObject* filePathList_py = PyList_New(seriesFilePaths.size());
        for (auto i = 0; i < seriesFilePaths.size(); i++)
        {
            std::string& filePath = seriesFilePaths.at(i);
            PyList_SetItem(filePathList_py, i, PyUnicode_FromString(filePath.c_str()));
        }
        pyObjects.emplace_back(filePathList_py);

        PyObject* func_args = PyTuple_New(2);
        PyTuple_SetItem(func_args, 0, filePathList_py);
        PyTuple_SetItem(func_args, 1, PyUnicode_FromString(outputDir.c_str()));
        pyObjects.emplace_back(func_args);

        std::cout << "[CONVERSION PROCESS] 75%" << std::endl;

        // 调用转换接口
        PyObject* func_py = PyObject_CallObject(func, func_args);
        if (!func_py)
        {
            std::logic_error ex("MultiVtkToGmsh failed.");
            throw std::exception(ex);
        }
        pyObjects.emplace_back(func_py);

        std::cout << "[CONVERSION PROCESS] 100%" << std::endl;
        convertState = 1;
    }
    catch (const std::exception& ex)
    {
        convertState = 0;
        std::cerr << "[ERROR] ConvertRstToGmsh: " << ex.what() << std::endl;
        if (PyErr_Occurred())
        {
            PyErr_Print();
        }
    }

    // 释放python空间
    // Py_XDECREF和Py_DECREF功能相同，但可以处理空指针
    for (auto it = pyObjects.rbegin(); it != pyObjects.rend(); it++)
    {
        Py_XDECREF(*it); // 释放python空间
    }
    std::vector<PyObject*>().swap(pyObjects);

    return convertState;
}